home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 4 / Amiga Tools 4.iso / grafix / raytracing / raylab / source / platform / amiga / amiga.c next >
C/C++ Source or Header  |  1996-02-17  |  13KB  |  507 lines

  1. /*
  2.     name:    amiga.c
  3.  
  4.     Amiga display routines
  5.     ----------------------
  6.  
  7.     Currently supported displaymodes:
  8.  
  9.     0 - No display (default)
  10.     1 - HAM6, lowres, non-interlaced
  11.     2 - Grayscale (16 colors), hires, interlaced
  12.  
  13. */
  14.  
  15.  
  16. #include  <stdio.h>
  17. #include  <dos.h>
  18. #include  <intuition/intuition.h>
  19. #include  <exec/exec.h>
  20. #include  <proto/intuition.h>
  21. #include  <proto/graphics.h>
  22. #include  <proto/exec.h>
  23.  
  24. #include  "defs.h"
  25. #include  "extern.h"
  26.  
  27.  
  28. /* Prototypes for some subroutines */
  29.  
  30. void OpenAmigaScreen(struct NewScreen *ScreenPars,struct NewWindow *WindowPars, UWORD Palette[], ULONG NumCols);
  31. void CloseAmigaScreen(void);
  32. UBYTE ConvertColorToHam6(unsigned char RGBColor[], int x, int y);
  33. UBYTE ConvertColorToGray(unsigned char RGBColor[], int x, int y);
  34. UBYTE MG_Dither8(UBYTE Value, int x, int y);
  35. void MG_Dither24(UBYTE RGBColor12[],unsigned char RGBColor24[], int x, int y);
  36. int BreakHandler(void);
  37.  
  38.  
  39. /* Some declarations */
  40.  
  41. #define SCREEN_TITLE_HEIGHT 11
  42.  
  43. #define DISPLAY_NONE 0            /* Different display modes */
  44. #define DISPLAY_HAM6 1
  45. #define DISPLAY_GRAY 2
  46.  
  47. #define HAM_MODE_PAL 0x00
  48. #define HAM_MODE_RED 0x20
  49. #define HAM_MODE_GRN 0x30
  50. #define HAM_MODE_BLU 0x10
  51.  
  52.  
  53. /* Some global variables */
  54.  
  55.     int    CurrentDisplayType;
  56.     UBYTE    Last12BitColor[3] = {0,0,0};
  57.  
  58.     struct    Screen *RL_Screen = NULL;
  59.     struct    Window *RL_Window = NULL;
  60.     struct    RastPort *RL_RastPort = NULL;
  61.     struct    ViewPort *RL_ViewPort = NULL;
  62.     struct    IntuitionBase *IntBase = NULL;
  63.     struct    GfxBase *GfxBase = NULL;
  64.  
  65.  
  66.     UWORD    Ham6Palette[16] = {
  67.             0x000, 0xAAA, 0x555, 0xFFF,
  68.             0x808, 0xF4A, 0xE00, 0x620,
  69.             0xF60, 0xFA8, 0xFE0, 0x080,
  70.             0x0D0, 0x0CC, 0x06F, 0x00A
  71.         };
  72.  
  73.     UWORD    GrayPalette[16] = {
  74.             0x000, 0x111, 0x222, 0x333,
  75.             0x444, 0x555, 0x666, 0x777,
  76.             0x888, 0x999, 0xAAA, 0xBBB,
  77.             0xCCC, 0xDDD, 0xEEE, 0xFFF
  78.         };
  79.  
  80.  
  81.     UWORD    DitherMask[16] = {
  82.             0x8000, 0x8080, 0x8410, 0x8888,
  83.             0x9224, 0xA492, 0xA94A, 0xAAAA,
  84.             0xD555, 0xD6B5, 0xDB6D, 0xEDDB,
  85.             0xF777, 0xFBEF, 0xFF7F, 0xFFFF
  86.         };
  87.  
  88.     UBYTE    DitherYTable[16] = {
  89.             0x08, 0x0B, 0x0E, 0x0F, 0x10, 0x0F, 0x0E, 0x0B,
  90.             0x08, 0x05, 0x02, 0x01, 0x00, 0x01, 0x02, 0x05
  91.         };
  92.  
  93.     struct TextAttr TopazAttr =
  94.         {(STRPTR)"topaz.font",TOPAZ_EIGHTY,0,0};
  95.  
  96.  
  97. /******************************************************************
  98.  *
  99.  *  OpenDisplay()
  100.  *
  101.  ******************************************************************/
  102.  
  103. long OpenDisplay(long DisplayType)
  104. {
  105.     long    Ret_OK;
  106.  
  107.     struct NewScreen ScreenPars =
  108.     {
  109.         0, 0,        /* LeftEdge, TopEdge        */
  110.         NULL, NULL,    /* Set screen size later    */
  111.         NULL,        /* Set depth later          */
  112.         2, 7,        /* DetailPen, BlockPen      */
  113.         NULL,        /* Set display-mode later   */
  114.         CUSTOMSCREEN,    /* SCREENQUIET ?            */
  115.         NULL,        /* Set font later           */
  116.         "RayLab 1.0 display",    /* Title            */
  117.         NULL,        /* No special gadgets       */
  118.         NULL        /* Nu custom bitmap         */
  119.     };
  120.  
  121.     struct NewWindow WindowPars =
  122.     {
  123.         0, SCREEN_TITLE_HEIGHT, /* LeftEdge, TopEdge*/
  124.         NULL, NULL,    /* Set screen size later    */
  125.         3, 7,        /* DetailPen, BlockPen      */
  126.         MENUPICK,    /* IDCMP                    */
  127.         SMART_REFRESH | BORDERLESS | NOCAREREFRESH | ACTIVATE,
  128.         NULL,        /* No special gadgets       */
  129.         NULL,        /* No checkmark             */
  130.         NULL,        /* No window title          */
  131.         NULL,        /* Set screen later         */
  132.         NULL,        /* No bitmap                */
  133.         NULL, NULL,    /* Set min size later       */
  134.         NULL, NULL,    /* Set max size later       */
  135.         CUSTOMSCREEN
  136.     };
  137.  
  138.  
  139.     RL_Screen = NULL; RL_Window = NULL;
  140.  
  141.     (void) onbreak((int (*)(void))BreakHandler);    /* Install break-handler */
  142.  
  143.     IntBase = (struct IntuitionBase *)
  144.         OpenLibrary("intuition.library",33);
  145.  
  146.     if(IntBase==NULL) {
  147.         fprintf(stderr,"Error: Could not open intuition.library; no display possible\n\n");
  148.         IntBase = NULL;
  149.     }
  150.     else {
  151.         GfxBase = (struct GfxBase *)
  152.             OpenLibrary("graphics.library",33);
  153.         if(GfxBase==NULL) {
  154.             fprintf(stderr,"Error: Could not open graphics.library; no display possible\n\n");
  155.             CloseLibrary((struct Library *)IntBase);
  156.             IntBase = NULL; GfxBase = NULL;
  157.         }
  158.     }
  159.  
  160.     if( (IntBase!=NULL) && (GfxBase!=NULL) ) {
  161.         if( (DisplayType>DISPLAY_NONE) && (DisplayType<=DISPLAY_GRAY) ) {
  162.         CurrentDisplayType = DisplayType;
  163.  
  164.         ScreenPars.Width = (SHORT)PicWidth;
  165.         ScreenPars.Height = (SHORT)(PicHeight+SCREEN_TITLE_HEIGHT);
  166.         ScreenPars.Font = &TopazAttr;
  167.  
  168.         WindowPars.Width = (SHORT)PicWidth;
  169.         WindowPars.Height = (SHORT)PicHeight;
  170.         WindowPars.MinWidth = WindowPars.MaxWidth = (SHORT)PicWidth;
  171.         WindowPars.MinHeight = WindowPars.MaxHeight = (SHORT)PicHeight;
  172.  
  173.         switch(CurrentDisplayType) {
  174.             case DISPLAY_HAM6:
  175.             ScreenPars.ViewModes = HAM;
  176.             ScreenPars.Depth = 6;
  177.             OpenAmigaScreen(&ScreenPars,&WindowPars,Ham6Palette,16L);
  178.             break;
  179.  
  180.             case DISPLAY_GRAY:
  181.             ScreenPars.ViewModes = HIRES | LACE;
  182.             ScreenPars.Depth = 4;
  183.             OpenAmigaScreen(&ScreenPars,&WindowPars,GrayPalette,16L);
  184.             break;
  185.  
  186.             case DISPLAY_NONE:
  187.             break;
  188.         }
  189.         }
  190.         else {
  191.         if(DisplayType!=DISPLAY_NONE)
  192.             fprintf(stderr,"Warning: Unsupported display type (%d), no display opened\n\n",DisplayType);
  193.         CurrentDisplayType = DISPLAY_NONE;
  194.         }
  195.     }
  196.     else {
  197.         CurrentDisplayType = DISPLAY_NONE;
  198.     }
  199.  
  200.     Ret_OK = 0L;
  201.     if(CurrentDisplayType!=DISPLAY_NONE) {
  202.         Ret_OK = 1L;
  203.     }
  204.  
  205.     return(Ret_OK);
  206. }
  207.  
  208.  
  209. /******************************************************************
  210.  *
  211.  *  CloseDisplay()
  212.  *
  213.  ******************************************************************/
  214.  
  215. void CloseDisplay(void)
  216. {
  217.     ULONG    done, signalmask, signals, class, code, menunum, itemnum;
  218.     struct    IntuiMessage *message;
  219.  
  220.     if((CurrentDisplayType!=0)&&(picturerendering!=0)) {
  221.         CloseAmigaScreen();
  222.     }
  223.     else if((CurrentDisplayType!=0)&&(picturerendering==0)) {
  224.         struct IntuiText ItemsText[] =
  225.         {
  226.         {2,1,JAM1,2,1,NULL," Close",    NULL}
  227.         };
  228.  
  229.         struct MenuItem Items[] =
  230.         {
  231.         {
  232.         NULL,        /* No more items            */
  233.         0, 1, 110, 10,    /* Left, top, width, height */
  234.         ITEMTEXT | COMMSEQ | ITEMENABLED | HIGHBOX,
  235.         0,        /* MutualExclude            */
  236.         NULL,        /* Set item text later      */
  237.         NULL,
  238.         'C',        /* Key equivalent           */
  239.         NULL,        /* Sub item                 */
  240.         MENUNULL    /* NextSelect               */
  241.         }
  242.         };
  243.  
  244.         struct Menu MenuPars =
  245.         {
  246.         NULL,        /* No more menus            */
  247.         0, 0, 120, 40,    /* Left, top, width, height */
  248.         MENUENABLED,    /* Flags                    */
  249.         "Action",    /* Menu name                */
  250.         NULL        /* Set first item later     */
  251.         };
  252.  
  253.         ItemsText[0].ITextFont = &TopazAttr;
  254.         Items[0].ItemFill = &ItemsText[0];
  255.         MenuPars.FirstItem = &Items[0];
  256.  
  257.         SetMenuStrip(RL_Window, &MenuPars);    /* Add menu */
  258.  
  259.  
  260.         signalmask = 1L << RL_Window->UserPort->mp_SigBit;
  261.         done = 0L;
  262.  
  263.         while( done == 0L ) {
  264.         signals = Wait(signalmask);
  265.         if((signals&signalmask)!=0L) {
  266.             while( message = (struct IntuiMessage *)GetMsg(RL_Window->UserPort) ) {
  267.             class = message->Class;
  268.             code = message->Code;
  269.             ReplyMsg((struct Message *)message);
  270.             if(class==MENUPICK) {
  271.                 menunum = MENUNUM(code);
  272.                 itemnum = ITEMNUM(code);
  273.                 if(menunum==0L) {
  274.                 if(itemnum==0L) {
  275.                     CloseAmigaScreen();
  276.                     done = 1L;
  277.                 }
  278.                 }
  279.             }
  280.             }
  281.         }
  282.         }
  283.     }
  284. }
  285.  
  286.  
  287. /******************************************************************
  288.  *
  289.  *  DisplayPlot()
  290.  *
  291.  ******************************************************************/
  292.  
  293. void DisplayPlot(int x, int y, unsigned char RGBColor[])
  294. {
  295.     switch(CurrentDisplayType) {
  296.         case DISPLAY_NONE:
  297.         break;
  298.  
  299.         case DISPLAY_HAM6:
  300.         SetAPen(RL_RastPort, ConvertColorToHam6(RGBColor,x,y));
  301.         (void) WritePixel(RL_RastPort,x,y);
  302.         break;
  303.  
  304.         case DISPLAY_GRAY:
  305.         SetAPen(RL_RastPort, ConvertColorToGray(RGBColor,x,y));
  306.         (void) WritePixel(RL_RastPort,x,y);
  307.         break;
  308.     }
  309. }
  310.  
  311.  
  312. /******************************************************************
  313.  
  314.     This routine is called if CTRL-C is issued
  315.  
  316.  ******************************************************************/
  317.  
  318. int BreakHandler(void)
  319. {
  320.     fprintf(stderr,"\n*** The execution of RayLab was terminated by the user\n");
  321.     cleanup();
  322.     return(1);    /* Exit RayLab after this */
  323. }
  324.  
  325.  
  326. /******************************************************************
  327.  
  328.     Some routines for converting 24-bit rgb colors to apropriate
  329.     display-modes
  330.  
  331.  ******************************************************************/
  332.  
  333.  
  334. UBYTE ConvertColorToHam6(unsigned char RGBColor[], int x, int y) {
  335.     UBYTE    New12BitColor[3];
  336.     UBYTE    HamMode, HamCol;
  337.     long    Diff12BitColor[3];
  338.     register long RGBDiff, t1, t2, t3, t4, i, BestColor;
  339.  
  340.     if(x==0) {
  341.         t1 = Ham6Palette[0];
  342.         Last12BitColor[0] = (t1&0xf00)>>8;
  343.         Last12BitColor[1] = (t1&0x0f0)>>4;
  344.         Last12BitColor[2] = t1&0x00f;
  345.     }
  346.  
  347. /* When dithering, it seems best to use the 24-bit color for comparsion: */
  348.  
  349.     Diff12BitColor[0] = (long)RGBColor[0]-(long)(Last12BitColor[0]<<4);
  350.     Diff12BitColor[1] = (long)RGBColor[1]-(long)(Last12BitColor[1]<<4);
  351.     Diff12BitColor[2] = (long)RGBColor[2]-(long)(Last12BitColor[2]<<4);
  352.     Diff12BitColor[0] *= Diff12BitColor[0];
  353.     Diff12BitColor[1] *= Diff12BitColor[1];
  354.     Diff12BitColor[2] *= Diff12BitColor[2];
  355.     HamMode = HAM_MODE_RED;
  356.     if(Diff12BitColor[1]>Diff12BitColor[0]) {
  357.         HamMode = HAM_MODE_GRN;
  358.         if(Diff12BitColor[2]>Diff12BitColor[1]) {
  359.             HamMode = HAM_MODE_BLU;
  360.         }
  361.     }
  362.     else {
  363.         if(Diff12BitColor[2]>Diff12BitColor[0]) {
  364.             HamMode = HAM_MODE_BLU;
  365.         }
  366.     }
  367.     Diff12BitColor[0] = Diff12BitColor[0]>>8;
  368.     Diff12BitColor[1] = Diff12BitColor[1]>>8;
  369.     Diff12BitColor[2] = Diff12BitColor[2]>>8;
  370.  
  371.     MG_Dither24(New12BitColor,RGBColor,x,y);
  372.  
  373.     switch(HamMode) {
  374.         case HAM_MODE_RED:
  375.         HamCol = Last12BitColor[0] = New12BitColor[0];
  376.         RGBDiff = Diff12BitColor[1] + Diff12BitColor[2];
  377.         break;
  378.         case HAM_MODE_GRN:
  379.         HamCol = Last12BitColor[1] = New12BitColor[1];
  380.         RGBDiff = Diff12BitColor[0] + Diff12BitColor[2];
  381.         break;
  382.         case HAM_MODE_BLU:
  383.         HamCol = Last12BitColor[2] = New12BitColor[2];
  384.         RGBDiff = Diff12BitColor[0] + Diff12BitColor[1];
  385.         break;
  386.     }
  387.  
  388.     BestColor = 100;
  389.     for(i=0;i<16;i++) {
  390.         t1 = (long)Ham6Palette[i];
  391.         t2 = ((t1&0xf00)>>8) - (long)New12BitColor[0]; t2 *= t2;
  392.         t3 = ((t1&0x0f0)>>4) - (long)New12BitColor[1]; t3 *= t3;
  393.         t4 = (t1&0x00f)      - (long)New12BitColor[2]; t4 *= t4;
  394.         t1 = t2+t3+t4;
  395.         if(RGBDiff>t1) {
  396.             RGBDiff = t1;
  397.             BestColor = i;
  398.         }
  399.     }
  400.     if(BestColor<16) {
  401.         HamMode = HAM_MODE_PAL;
  402.         HamCol  = (UBYTE)BestColor;
  403.         t1 = Ham6Palette[BestColor];
  404.         Last12BitColor[0] = (t1&0xf00)>>8;
  405.         Last12BitColor[1] = (t1&0x0f0)>>4;
  406.         Last12BitColor[2] = t1&0x00f;
  407.     }
  408.  
  409.     return((UBYTE)(HamMode | (HamCol&0x0f)));
  410. }
  411.  
  412.  
  413.  
  414. UBYTE ConvertColorToGray(unsigned char RGBColor[], int x, int y)
  415. {
  416.     UBYTE    Gray;
  417.  
  418.     Gray = (UBYTE)(((UWORD)RGBColor[0]+(UWORD)RGBColor[1]+(UWORD)RGBColor[2])/(UWORD)3);
  419.     return(MG_Dither8(Gray,x,y));
  420. }
  421.  
  422.  
  423.  
  424. /* This is some strange dithering method that */
  425. /* I managed to produce late one night        */
  426.  
  427. UBYTE MG_Dither8(UBYTE Value, int x, int y)
  428. {
  429.     UBYTE    Dithered;
  430.  
  431.     Dithered = Value>>4;
  432.     if(Dithered<15) {
  433.         if(((0x01<<(((y<<2)+x+DitherYTable[y&0x000f])&0x000f))&DitherMask[Value&0x0f])!=0) Dithered++;
  434.     }
  435.     return(Dithered);
  436. }
  437.  
  438.  
  439. void MG_Dither24(UBYTE RGBColor12[], unsigned char RGBColor24[], int x, int y)
  440. {
  441.     register int    Dither;
  442.  
  443.     RGBColor12[0] = (RGBColor24[0]>>4)&0x0f;
  444.     RGBColor12[1] = (RGBColor24[1]>>4)&0x0f;
  445.     RGBColor12[2] = (RGBColor24[2]>>4)&0x0f;
  446.     Dither = 0x01<<(((y<<2)+x+DitherYTable[y&0x000f])&0x000f);
  447.     if((RGBColor12[0]<15)&(Dither&DitherMask[RGBColor24[0]&0x0f])!=0) RGBColor12[0]++;
  448.     if((RGBColor12[1]<15)&(Dither&DitherMask[RGBColor24[1]&0x0f])!=0) RGBColor12[1]++;
  449.     if((RGBColor12[2]<15)&(Dither&DitherMask[RGBColor24[2]&0x0f])!=0) RGBColor12[2]++;
  450. }
  451.  
  452.  
  453. /*
  454.    A routine for simplifying the opening of Amiga screens and windows
  455. */
  456.  
  457. void OpenAmigaScreen(struct NewScreen *ScreenPars,struct NewWindow *WindowPars, UWORD Palette[], ULONG NumCols)
  458. {
  459.     RL_Screen = (struct Screen *)OpenScreen(ScreenPars);
  460.     if(RL_Screen!=NULL) {
  461.         WindowPars->Screen = RL_Screen;
  462.         RL_Window = (struct Window *)OpenWindow(WindowPars);
  463.         if(RL_Window!=NULL) {
  464.         RL_RastPort = RL_Window->RPort;
  465.         RL_ViewPort = &(RL_Screen->ViewPort);
  466.         LoadRGB4(RL_ViewPort,Palette,NumCols);
  467.         SetDrMd(RL_RastPort, JAM1);
  468.         }
  469.         else {
  470.         RL_RastPort = NULL;
  471.         fprintf(stderr,"Error: Could not open display window\n\n");
  472.         CurrentDisplayType = DISPLAY_NONE;
  473.         CloseScreen(RL_Screen);
  474.         RL_Screen = NULL; RL_Window = NULL;
  475.         }
  476.     }
  477.     else {
  478.         fprintf(stderr,"Error: Could not open display screen\n\n");
  479.         CurrentDisplayType = DISPLAY_NONE;
  480.         RL_Screen = NULL; RL_Window = NULL;
  481.     }
  482. }
  483.  
  484.  
  485. void CloseAmigaScreen(void)
  486. {
  487.     CurrentDisplayType = DISPLAY_NONE;
  488.     if(RL_Window!=NULL) {
  489.         if(RL_Window->MenuStrip)
  490.             ClearMenuStrip(RL_Window);    /* Remove menu  */
  491.         CloseWindow(RL_Window);        /* Close window */
  492.         RL_Window = NULL;
  493.     }
  494.     if(RL_Screen!=NULL) {
  495.         CloseScreen(RL_Screen);        /* Close screen */
  496.         RL_Screen = NULL;
  497.     }
  498.     if(GfxBase!=NULL) {
  499.         CloseLibrary((struct Library *)GfxBase);  /* Close graphics.library */
  500.         GfxBase = NULL;
  501.     }
  502.     if(IntBase!=NULL) {
  503.         CloseLibrary((struct Library *)IntBase);  /* Close intuition.library */
  504.         IntBase = NULL;
  505.     }
  506. }
  507.